﻿using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.XWPF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace CoreLims.Models.CoreLims
{
    public static class ReportExtension
    {
        /// <summary>
        /// 生成采样标签
        /// </summary>
        /// <param name="report"></param>
        /// <param name="ReportTemplate">模板位置和名称</param>
        /// <param name="dir">生成文件存放路径</param>
        public static string CreateSamplingLabel(this Report report, IQueryable<object> sampleList, string ReportTemplate, string dir)
        {
            if (!File.Exists(ReportTemplate))
                return "文件模板没找到！";

            XWPFDocument documentReport, documentData;
            using (FileStream fs = new FileStream(ReportTemplate, FileMode.Open, FileAccess.ReadWrite))
            {
                documentReport = new XWPFDocument(fs);
            }

            int a = 0;
            foreach (var sample in sampleList)
            {
                var paraList = new List<(string, string)>();
                paraList.Add(("@code128", sample.GetType().GetProperty("SampleId").GetValue(sample).ToString()));

                if (sample.GetType().GetProperty("HandlingTime").GetValue(sample) == null)
                    return "选择的样品还未执行采样操作！";

                var cellList = new List<(string, string)>
                {
                    ("@SampleId", sample.GetType().GetProperty("SampleId").GetValue(sample).ToString()),
                    ("@Classification", sample.GetType().GetProperty("Classification").GetValue(sample).ToString()),
                    ("@GenricClass", sample.GetType().GetProperty("GenricClass").GetValue(sample).ToString()),
                    ("@HandlingTime", sample.GetType().GetProperty("HandlingTime").GetValue(sample).ToString().Split(' ')[0]),
                    ("@Name", sample.GetType().GetProperty("Name").GetValue(sample).ToString())
                };

                if (a == 0) // 第一个标签要使用模板文件，后面的标签需要复制
                {
                    ReplaceSpecifiedString(documentReport, paraList);
                    ReplaceTableSpecifiedString(documentReport, cellList);
                }
                else
                {
                    using (FileStream fs = new FileStream(ReportTemplate, FileMode.Open, FileAccess.ReadWrite))
                    {
                        documentData = new XWPFDocument(fs);
                    }
                    ReplaceSpecifiedString(documentData, paraList);
                    ReplaceTableSpecifiedString(documentData, cellList);
                    CopyTemplateLabPage(documentReport, documentData);
                }
                a++;
            }

            dir = dir + @"\TEMP\";
            var fileID = Guid.NewGuid().ToString();
            WriteToFile(dir, documentReport, fileID + ".docx");

            return "成功," + fileID + ".docx";
        }

        /// <summary>
        /// 生成样品标签，跟流程无关
        /// </summary>
        /// <param name="report"></param>
        /// <param name="sampleList"></param>
        /// <param name="ReportTemplate"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        public static string CreateSampleLabel(this Report report, List<SampleSample> sampleList, string ReportTemplate, string dir)
        {
            if (!File.Exists(ReportTemplate))
                return "文件模板没找到！";

            XWPFDocument documentReport, documentData;
            using (FileStream fs = new FileStream(ReportTemplate, FileMode.Open, FileAccess.ReadWrite))
            {
                documentReport = new XWPFDocument(fs);
            }

            int a = 0;
            foreach (var sample in sampleList)
            {
                var paraList = new List<(string, string)>();
                paraList.Add(("@code128", sample.SampleId));

                var cellList = new List<(string, string)>
                {
                    ("@SampleId", sample.SampleId),
                    ("@Classification", sample.Classification),
                    ("@GenricClass", sample.GenricClass),
                    ("@Name", sample.Name)
                };

                if (a == 0) // 第一个标签要使用模板文件，后面的标签需要复制
                {
                    ReplaceSpecifiedString(documentReport, paraList);
                    ReplaceTableSpecifiedString(documentReport, cellList);
                }
                else
                {
                    using (FileStream fs = new FileStream(ReportTemplate, FileMode.Open, FileAccess.ReadWrite))
                    {
                        documentData = new XWPFDocument(fs);
                    }
                    ReplaceSpecifiedString(documentData, paraList);
                    ReplaceTableSpecifiedString(documentData, cellList);
                    CopyTemplateLabPage(documentReport, documentData);
                }
                a++;
            }

            dir = dir + @"\TEMP\";
            var fileID = Guid.NewGuid().ToString();
            WriteToFile(dir, documentReport, fileID + ".docx");

            return "成功," + fileID + ".docx";
        }

        private static void CopyTemplateLabPage(XWPFDocument documentReport, XWPFDocument documentData)
        {
            int aq = 0;
            int tableIndex = documentReport.Tables.Count;
            foreach (var item in documentData.Paragraphs) // 复制段落
            {
                if (aq == 2)
                {
                    documentReport.CreateTable();
                    documentReport.SetTable(tableIndex, documentData.Tables[0]);
                }
                var runa = documentReport.Paragraphs.Count;
                documentReport.CreateParagraph();
                documentReport.SetParagraph(item, runa);
                aq++;
            }
        }

        private static void WriteToFile(string dir, XWPFDocument documentOriginal, string FileName)
        {
            MemoryStream ms = new System.IO.MemoryStream();
            documentOriginal.Write(ms);

            DirectoryInfo savePath = new DirectoryInfo(dir);
            if (!savePath.Exists)
                Directory.CreateDirectory(dir);

            FileStream outfs = new FileStream(dir + FileName, FileMode.Create);
            BinaryWriter bw = new BinaryWriter(outfs);
            bw.Write(ms.GetBuffer());

            ms.Close();
            bw.Close();
            outfs.Close();
        }

        /// <summary>
        /// 在文本段落中搜索指定字符串并替换
        /// </summary>
        /// <param name="documentReport"></param>
        /// <param name="tupleList">Item1被搜索的字符串，Item2替换的字符串</param>
        private static void ReplaceSpecifiedString (XWPFDocument documentReport, List<(string, string)> tupleList)
        {
            foreach (var tuple in tupleList)
            {
                foreach (var para in documentReport.Paragraphs)
                {
                    if (para.ParagraphText.Contains(tuple.Item1))
                    {
                        para.ReplaceText(tuple.Item1, tuple.Item2);
                    }
                }
            }
        }

        /// <summary>
        /// 在文档中指定的表格里，查询并替换字符串。
        /// </summary>
        /// <param name="documentReport"></param>
        /// <param name="tabIndex">表格索引</param>
        /// <param name="tupleList">Item1被搜索的字符串，Item2替换的字符串</param>
        private static void ReplaceTableSpecifiedString(XWPFDocument documentReport,List<(string, string)> tupleList)
        {
            foreach (var tuple in tupleList)
            {
                foreach (var row in documentReport.Tables[0].Rows)
                {
                    var cells = row.GetTableCells();
                    foreach (var cell in cells)
                    {
                        if (cell.Paragraphs[0].ParagraphText.Contains(tuple.Item1))
                        {
                            cell.Paragraphs[0].ReplaceText(tuple.Item1, tuple.Item2);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 计算文件大小
        /// </summary>
        /// <param name="filesize"></param>
        /// <returns></returns>
        private static string GetSise(long filesize)
        {
            if (filesize < 0)
                return "0";
            else if (filesize >= 1024 * 1024 * 1024)
                return string.Format("{0:0}GB", (double)filesize / (1024 * 1024 * 1024));
            else if (filesize >= 1024 * 1024)
                return string.Format("{0:0}MB", (double)filesize / (1024 * 1024));
            else if (filesize >= 1024)
                return string.Format("{0:0}KB", (double)filesize / (1024));
            else
                return string.Format("{0:0}bytes", filesize);
        }

        /// <summary>
        /// 样品信息导出到EXCEL文件
        /// </summary>
        /// <param name="report"></param>
        /// <param name="List"></param>
        /// <param name="ReportTemplate"></param>
        /// <returns></returns>
        public static string SampleToExcel(this Report report, IList<SampleSample> List, string ReportTemplate)
        {
            var path = ReportTemplate + @"\样品导出模板.xlsx";
            string filename = null;
            if (!File.Exists(path))
                return "文件模板没找到！";

            using (FileStream ps = new FileStream(path, FileMode.Open, FileAccess.ReadWrite))
            {
                XSSFWorkbook workbook = new XSSFWorkbook(ps);
                ISheet sheet = workbook.GetSheetAt(0);
                int a = 0;
                IRow row = sheet.CreateRow(0);

                row.CreateCell(0).SetCellValue("ID");
                row.CreateCell(1).SetCellValue("样品ID");
                row.CreateCell(2).SetCellValue("样品编号");
                row.CreateCell(3).SetCellValue("样品批次号");

                a = 1;
                foreach (SampleSample sample in List) 
                {
                    row = sheet.CreateRow(a);
                    row.CreateCell(0).SetCellValue(sample.Id);
                    row.CreateCell(1).SetCellValue(sample.SampleId);
                    row.CreateCell(2).SetCellValue(sample.SampleNumber);
                    row.CreateCell(3).SetCellValue(sample.BatchId);
                    a++;
                }

                //另存文件       
                var fileID = Guid.NewGuid().ToString();
                filename = fileID + ".xlsx";
                using (FileStream outfs = new FileStream(ReportTemplate + @"\TEMP\" + filename, FileMode.Create, FileAccess.Write))
                {
                    workbook.Write(outfs);
                }
            }
            return "成功," + filename;
        }

    }
}
